#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
导出管理器模块
管理后台导出任务，支持多个并发导出任务和进度跟踪
"""

import logging
import uuid
import time
from typing import Dict, List, Any, Optional, Callable
from dataclasses import dataclass
from enum import Enum
from pathlib import Path

from PySide6.QtCore import QObject, Signal, QThread, QTimer
from PySide6.QtWidgets import QApplication

from core.export_service import get_export_service


# 初始化日志记录器
logger = logging.getLogger("export_manager")


class ExportStatus(Enum):
    """导出状态枚举"""
    PENDING = "pending"      # 等待中
    RUNNING = "running"      # 进行中
    COMPLETED = "completed"  # 已完成
    FAILED = "failed"        # 失败
    CANCELLED = "cancelled"  # 已取消


@dataclass
class ExportTask:
    """导出任务数据类"""
    task_id: str
    file_path: str
    format_type: str
    data_info: str  # 数据描述，如 "1000 行 x 5 列"
    status: ExportStatus
    progress: int  # 0-100
    start_time: Optional[float] = None
    end_time: Optional[float] = None
    error_message: Optional[str] = None
    total_rows: int = 0
    processed_rows: int = 0
    
    @property
    def duration(self) -> Optional[float]:
        """获取任务持续时间"""
        if self.start_time is None:
            return None
        end = self.end_time or time.time()
        return end - self.start_time
    
    @property
    def file_name(self) -> str:
        """获取文件名"""
        return Path(self.file_path).name
    
    @property
    def status_text(self) -> str:
        """获取状态文本"""
        if self.status == ExportStatus.PENDING:
            return "等待中"
        elif self.status == ExportStatus.RUNNING:
            return f"进行中 ({self.progress}%)"
        elif self.status == ExportStatus.COMPLETED:
            return "已完成"
        elif self.status == ExportStatus.FAILED:
            return "失败"
        elif self.status == ExportStatus.CANCELLED:
            return "已取消"
        return "未知"


class ExportWorker(QThread):
    """导出工作线程"""
    
    # 信号定义
    progress_updated = Signal(str, int)  # task_id, progress
    task_completed = Signal(str, bool, str)  # task_id, success, message
    
    def __init__(self, task: ExportTask, data: List[List], columns: List[str]):
        """初始化导出工作线程
        
        Args:
            task: 导出任务
            data: 要导出的数据
            columns: 列名列表
        """
        super().__init__()
        self.task = task
        self.data = data
        self.columns = columns
        self.export_service = get_export_service()
        self._cancelled = False
        
    def run(self):
        """执行导出任务"""
        try:
            logger.info(f"开始导出任务: {self.task.task_id}")
            
            # 检查是否被取消
            if self._cancelled:
                self.task_completed.emit(self.task.task_id, False, "任务已取消")
                return
            
            # 模拟进度更新
            total_rows = len(self.data)
            batch_size = max(1, total_rows // 20)  # 分20批处理
            
            # 开始导出
            self.progress_updated.emit(self.task.task_id, 10)
            
            # 检查Excel限制
            EXCEL_MAX_ROWS = 1048576
            export_data = self.data
            warning_message = ""
            
            if self.task.format_type == "excel" and len(self.data) > EXCEL_MAX_ROWS:
                export_data = self.data[:EXCEL_MAX_ROWS]
                warning_message = f"\n注意：由于Excel限制，只导出了前 {EXCEL_MAX_ROWS:,} 行数据。"
            
            self.progress_updated.emit(self.task.task_id, 30)
            
            # 检查是否被取消
            if self._cancelled:
                self.task_completed.emit(self.task.task_id, False, "任务已取消")
                return
            
            # 执行实际导出
            success, message = self.export_service.export_data(
                data=export_data,
                file_path=self.task.file_path,
                format_type=self.task.format_type
            )
            
            self.progress_updated.emit(self.task.task_id, 90)
            
            # 检查是否被取消
            if self._cancelled:
                self.task_completed.emit(self.task.task_id, False, "任务已取消")
                return
            
            # 完成
            self.progress_updated.emit(self.task.task_id, 100)
            
            if success:
                final_message = message + warning_message
                self.task_completed.emit(self.task.task_id, True, final_message)
            else:
                self.task_completed.emit(self.task.task_id, False, message)
                
        except Exception as e:
            logger.error(f"导出任务失败: {str(e)}")
            self.task_completed.emit(self.task.task_id, False, f"导出过程中发生错误: {str(e)}")
    
    def cancel(self):
        """取消任务"""
        self._cancelled = True


class ExportManager(QObject):
    """导出管理器"""
    
    # 信号定义
    task_added = Signal(str)  # task_id
    task_updated = Signal(str)  # task_id
    task_completed = Signal(str, bool, str)  # task_id, success, message
    
    def __init__(self):
        """初始化导出管理器"""
        super().__init__()
        self.tasks: Dict[str, ExportTask] = {}
        self.workers: Dict[str, ExportWorker] = {}
        
        # 清理定时器 - 定期清理已完成的任务
        self.cleanup_timer = QTimer()
        self.cleanup_timer.timeout.connect(self._cleanup_completed_tasks)
        self.cleanup_timer.start(60000)  # 每分钟清理一次
        
    def create_export_task(self, file_path: str, format_type: str, data: List[List], 
                          columns: List[str], data_info: str) -> str:
        """创建导出任务
        
        Args:
            file_path: 导出文件路径
            format_type: 导出格式
            data: 要导出的数据
            columns: 列名列表
            data_info: 数据描述
            
        Returns:
            任务ID
        """
        task_id = str(uuid.uuid4())
        
        # 创建任务
        task = ExportTask(
            task_id=task_id,
            file_path=file_path,
            format_type=format_type,
            data_info=data_info,
            status=ExportStatus.PENDING,
            progress=0,
            total_rows=len(data)
        )
        
        self.tasks[task_id] = task
        
        # 创建工作线程
        worker = ExportWorker(task, data, columns)
        worker.progress_updated.connect(self._on_progress_updated)
        worker.task_completed.connect(self._on_task_completed)
        worker.finished.connect(lambda: self._cleanup_worker(task_id))
        
        self.workers[task_id] = worker
        
        # 发出信号
        self.task_added.emit(task_id)
        
        logger.info(f"创建导出任务: {task_id}, 文件: {file_path}")
        
        return task_id
    
    def start_task(self, task_id: str) -> bool:
        """启动导出任务
        
        Args:
            task_id: 任务ID
            
        Returns:
            是否成功启动
        """
        if task_id not in self.tasks or task_id not in self.workers:
            return False
            
        task = self.tasks[task_id]
        worker = self.workers[task_id]
        
        if task.status != ExportStatus.PENDING:
            return False
            
        # 更新任务状态
        task.status = ExportStatus.RUNNING
        task.start_time = time.time()
        
        # 启动工作线程
        worker.start()
        
        self.task_updated.emit(task_id)
        logger.info(f"启动导出任务: {task_id}")
        
        return True
    
    def cancel_task(self, task_id: str) -> bool:
        """取消导出任务
        
        Args:
            task_id: 任务ID
            
        Returns:
            是否成功取消
        """
        if task_id not in self.tasks:
            return False
            
        task = self.tasks[task_id]
        
        if task.status not in [ExportStatus.PENDING, ExportStatus.RUNNING]:
            return False
            
        # 更新任务状态
        task.status = ExportStatus.CANCELLED
        task.end_time = time.time()
        
        # 取消工作线程
        if task_id in self.workers:
            worker = self.workers[task_id]
            worker.cancel()
            if worker.isRunning():
                worker.quit()
                worker.wait(3000)  # 等待3秒
        
        self.task_updated.emit(task_id)
        logger.info(f"取消导出任务: {task_id}")
        
        return True
    
    def get_task(self, task_id: str) -> Optional[ExportTask]:
        """获取任务信息
        
        Args:
            task_id: 任务ID
            
        Returns:
            任务信息
        """
        return self.tasks.get(task_id)
    
    def get_all_tasks(self) -> List[ExportTask]:
        """获取所有任务
        
        Returns:
            任务列表
        """
        return list(self.tasks.values())
    
    def get_active_tasks(self) -> List[ExportTask]:
        """获取活跃任务（等待中和进行中）
        
        Returns:
            活跃任务列表
        """
        return [task for task in self.tasks.values() 
                if task.status in [ExportStatus.PENDING, ExportStatus.RUNNING]]
    
    def get_recent_tasks(self, limit: int = 10) -> List[ExportTask]:
        """获取最近的任务
        
        Args:
            limit: 限制数量
            
        Returns:
            最近任务列表
        """
        all_tasks = list(self.tasks.values())
        # 按开始时间排序
        all_tasks.sort(key=lambda t: t.start_time or 0, reverse=True)
        return all_tasks[:limit]
    
    def _on_progress_updated(self, task_id: str, progress: int):
        """进度更新处理"""
        if task_id in self.tasks:
            task = self.tasks[task_id]
            task.progress = progress
            task.processed_rows = int(task.total_rows * progress / 100)
            self.task_updated.emit(task_id)
    
    def _on_task_completed(self, task_id: str, success: bool, message: str):
        """任务完成处理"""
        if task_id in self.tasks:
            task = self.tasks[task_id]
            task.status = ExportStatus.COMPLETED if success else ExportStatus.FAILED
            task.progress = 100 if success else task.progress
            task.end_time = time.time()
            if not success:
                task.error_message = message
            
            self.task_updated.emit(task_id)
            self.task_completed.emit(task_id, success, message)
            
            logger.info(f"导出任务完成: {task_id}, 成功: {success}")
    
    def _cleanup_worker(self, task_id: str):
        """清理工作线程"""
        if task_id in self.workers:
            worker = self.workers[task_id]
            worker.deleteLater()
            del self.workers[task_id]
    
    def _cleanup_completed_tasks(self):
        """清理已完成的任务"""
        current_time = time.time()
        tasks_to_remove = []
        
        for task_id, task in self.tasks.items():
            # 清理1小时前完成的任务
            if (task.status in [ExportStatus.COMPLETED, ExportStatus.FAILED, ExportStatus.CANCELLED] and
                task.end_time and current_time - task.end_time > 3600):
                tasks_to_remove.append(task_id)
        
        for task_id in tasks_to_remove:
            if task_id in self.tasks:
                del self.tasks[task_id]
            if task_id in self.workers:
                worker = self.workers[task_id]
                worker.deleteLater()
                del self.workers[task_id]
        
        if tasks_to_remove:
            logger.info(f"清理了 {len(tasks_to_remove)} 个已完成的导出任务")


# 全局导出管理器实例
_export_manager = None


def get_export_manager() -> ExportManager:
    """获取导出管理器实例
    
    Returns:
        导出管理器实例
    """
    global _export_manager
    if _export_manager is None:
        _export_manager = ExportManager()
    return _export_manager 